#!/usr/bin/env python3
import subprocess
#!/usr/bin/env python3
import subprocess

# 9
lv0 = {
    "decl_const1": (1, False, False),
    "decl_int": (1, False, False),
    "input_float": (1, True, False),
    "decl_const2": (1, False, False),
    "decl_const": (1, False, False),
    "decl_float_array": (1, False, False),
    "input_int": (1, True, False),
    "decl_int_array": (1, False, False),
    "decl_float": (1, False, False),
}

# 4
lv1 = {
    "call4": (1, False, False),
    "call3": (1, False, False),
    "call2": (1, False, False),
    "call1": (1, False, False),
}

# 4
lv2 = {
    "sub1": (1, False, False),
    "sub2": (1, False, False),
    "add2": (1, False, False),
    "add1": (1, False, False),
}

# 9
lv3 = {
    "mod3": (1, False, False),
    "err_mod2":(1, False, True),
    "mod1": (1, False, False),
    "mul1": (1, False, False),
    "mul2": (1, False, False),
    "div1": (1, False, False),
    "div3": (1, False, False),
    "div2": (1, False, False),
    "div4": (1, False, False),
}

# 7
lv4 = {
    "while1": (1, False, False),
    "if-else1": (1, False, False),
    "while2": (1, False, False),
    "if-else2": (1, False, False),
    "while3": (1, False, False),
    "while4": (1, False, False),
    "while5": (1, False, False),
}

# 4
lv5 = {
    "break1": (1, False, False),
    "break2": (1, False, False),
    "continue1": (1, False, False),
    "continue2": (1, False, False),
}

# 6
lv6 = {
    "const_array3": (1, False, False),
    "const_array2": (1, False, False),
    "const_array1": (1, False, False),
    "const_array5": (1, False, False),
    "const_array4": (1, False, False),
    "const_array6": (1, False, False),
}

suite = [
    ("lv0", lv0, 0),
    ("lv1", lv1, 0),
    ("lv2", lv2, 0),
    ("lv3", lv3, 0),
    ("lv4", lv4, 0),
    ("lv5", lv5, 0),
    ("lv6", lv6, 0)
]

def eval():
    f = open("eval_result", 'w')
    EXE_PATH = "../../../build/sysy"
    TEST_BASE_PATH = "./testcases/"
    ANSWER_BASE_PATH = "./answers/"
    total_points = 0
    for level in suite:
        lv_points = 0
        has_bonus = True
        level_name = level[0]
        bonus = level[2]
        cases = level[1]
        f.write('===========%s START========\n' % level_name)
        for case in cases:
            f.write('%s:' % case)
            TEST_PATH = TEST_BASE_PATH + level_name + "/" + case
            ANSWER_PATH = ANSWER_BASE_PATH + level_name + "/" + case
            score = cases[case][0]
            need_input = cases[case][1]
            need_abort = cases[case][2]

            # 打印当前正在测试的文件名
            print(f"[*]Testing {TEST_PATH}.sysy...")

            # 先编译程序
            try:
                result = subprocess.run([EXE_PATH, "-o", TEST_PATH + ".ll", "-emit-llvm", TEST_PATH + ".sysy"], stderr=subprocess.PIPE, timeout=1)
            except Exception as _:
                f.write('\tFail\n')
                continue

            if result.returncode == 0:
                subprocess.run(["clang", "-O0", "-w", "-no-pie", TEST_PATH + ".ll", "-o", TEST_PATH, "-L", "../../../build", "-lsysy_io"])
                input_option = None
                if need_input:
                    with open(ANSWER_PATH + ".in", "rb") as fin:
                        input_option = fin.read()

                try:
                    # 执行程序
                    result = subprocess.run([TEST_PATH], input=input_option, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=1)
                    # 读取答案文件并将其转为字符串进行比较
                    with open(ANSWER_PATH + ".out", "r") as fout:
                        expected_output = fout.read().strip()

                    actual_output = result.stdout.decode().strip()

                    # 字符串比较，忽略输出中的额外空格
                    if actual_output == expected_output:
                        f.write('\tSuccess\n')
                        lv_points += score
                    else:
                        f.write('\tFail\n')
                        has_bonus = False

                except Exception as _:
                    f.write('\tFail\n')
                    has_bonus = False
                finally:
                    subprocess.call(["rm", "-rf", TEST_PATH, TEST_PATH + ".o", TEST_PATH + ".ll"])

            else:
                if need_abort:
                    if result.returncode in (134, -6):
                        f.write('\tSuccess\n')
                        lv_points += score
                    else:
                        f.write('\tFail(Should Abort)\n')
                        has_bonus = False
                else:
                    f.write('\tFail\n')
                    has_bonus = False

        if has_bonus:
            lv_points += bonus

        total_points += lv_points
        f.write('points of %s is: %d\n' % (level_name, lv_points))
        f.write('===========%s END========\n\n' % level_name)
    f.write('total points: %d\n' % total_points)



if __name__ == "__main__":
    eval()
